home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / EffectParam / EffectParam.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-28  |  43.5 KB  |  1,025 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: EffectParam.cpp
  3. //
  4. // Starting point for new Direct3D applications
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved.
  7. //--------------------------------------------------------------------------------------
  8. #include "dxstdafx.h"
  9. #include "resource.h"
  10. #include <crtdbg.h>
  11.  
  12.  
  13. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  14. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  15.  
  16. // SCROLL_TIME dictates the time one scroll op takes, in seconds.
  17. #define SCROLL_TIME 0.5f
  18.  
  19. struct MESHLISTDATA
  20. {
  21.     WCHAR wszName[MAX_PATH];
  22.     WCHAR wszFile[MAX_PATH];
  23.     DWORD dwNumMat;  // Number of materials.  To be filled in when loading this mesh.
  24. } g_MeshListData[] =
  25. {
  26.     { L"Car", L"car2.x", 0 },
  27.     { L"Banded Earth", L"sphereband.x", 0 },
  28.     { L"Dwarf", L"dwarf\\DwarfWithEffectInstance.x", 0 },
  29.     { L"Virus", L"cytovirus.x", 0 },
  30.     { L"Car", L"car2.x", 0 },
  31.     { L"Banded Earth", L"sphereband.x", 0 },
  32.     { L"Dwarf", L"dwarf\\DwarfWithEffectInstance.x", 0 },
  33. };
  34.  
  35.  
  36. struct MESHVERTEX
  37. {
  38.     D3DXVECTOR3 Position;
  39.     D3DXVECTOR3 Normal;
  40.     D3DXVECTOR2 Tex;
  41.  
  42.     const static D3DVERTEXELEMENT9 Decl[4];
  43. };
  44.  
  45. const D3DVERTEXELEMENT9 MESHVERTEX::Decl[] =
  46. {
  47.     { 0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
  48.     { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   0 },
  49.     { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
  50.     D3DDECL_END()
  51. };
  52.  
  53.  
  54. struct CMeshMaterial
  55. {
  56.     ID3DXEffect *m_pEffect;
  57.     D3DXHANDLE   m_hParam;
  58.     IDirect3DTexture9 *m_pTexture;
  59.  
  60. public:
  61.     CMeshMaterial()
  62.     {
  63.         m_pEffect = NULL;
  64.         m_hParam = NULL;
  65.         m_pTexture = NULL;
  66.     }
  67.     ~CMeshMaterial()
  68.     {
  69.         SAFE_RELEASE( m_pEffect );
  70.         SAFE_RELEASE( m_pTexture );
  71.     }
  72.     const CMeshMaterial &operator=( const CMeshMaterial &rhs )
  73.     {
  74.         m_pEffect = rhs.m_pEffect;
  75.         m_hParam = rhs.m_hParam;
  76.         m_pTexture = rhs.m_pTexture;
  77.         m_pEffect->AddRef();
  78.         m_pTexture->AddRef();
  79.         return *this;
  80.     }
  81. };
  82.  
  83.  
  84. extern ID3DXEffect* g_pEffect;
  85. extern IDirect3DTexture9* g_pDefaultTex;
  86. extern IDirect3DCubeTexture9* g_pEnvMapTex;
  87.  
  88.  
  89. class CEffectMesh
  90. {
  91.     WCHAR          m_wszMeshFile[MAX_PATH];
  92.     ID3DXMesh     *m_pMesh;
  93.     CMeshMaterial *m_pMaterials;
  94.     DWORD          m_dwNumMaterials;
  95.  
  96. public:
  97.     CEffectMesh()
  98.     {
  99.         m_pMesh = NULL;
  100.         m_pMaterials = NULL;
  101.         m_dwNumMaterials = 0;
  102.     }
  103.     CEffectMesh( const CEffectMesh &old )
  104.     {
  105.         m_pMesh = NULL; m_pMaterials = NULL;
  106.         *this = old;
  107.     }
  108.     ~CEffectMesh()
  109.     {
  110.         Destroy();
  111.     }
  112.     const CEffectMesh &operator=( const CEffectMesh &rhs )
  113.     {
  114.         if( this == &rhs )
  115.             return *this;
  116.  
  117.         lstrcpyW( m_wszMeshFile, rhs.m_wszMeshFile );
  118.         m_dwNumMaterials = rhs.m_dwNumMaterials;
  119.         SAFE_RELEASE( m_pMesh );
  120.         if( ( m_pMesh = rhs.m_pMesh ) != 0 ) m_pMesh->AddRef();
  121.         delete[] m_pMaterials;
  122.         m_pMaterials = new CMeshMaterial[m_dwNumMaterials];
  123.         for( UINT i = 0; i < m_dwNumMaterials; ++i )
  124.             m_pMaterials[i] = rhs.m_pMaterials[i];
  125.         return *this;
  126.     }
  127.     DWORD GetNumMaterials() const { return m_dwNumMaterials; }
  128.     ID3DXMesh *GetMesh() { return m_pMesh; }
  129.  
  130.     HRESULT Create( LPCWSTR wszFileName, IDirect3DDevice9 *pd3dDevice );
  131.     HRESULT Destroy()
  132.     {
  133.         delete[] m_pMaterials;
  134.         m_pMaterials = NULL;
  135.         m_dwNumMaterials = 0;
  136.         SAFE_RELEASE( m_pMesh );
  137.         return S_OK;
  138.     }
  139.     void Render( IDirect3DDevice9 *pd3dDevice )
  140.     {
  141.         HRESULT hr;
  142.  
  143.         for( UINT i = 0; i < m_dwNumMaterials; ++i )
  144.         {
  145.             CMeshMaterial *pMat = &m_pMaterials[i];
  146.             V( pMat->m_pEffect->ApplyParameterBlock( pMat->m_hParam ) );
  147.  
  148.             UINT cPasses;
  149.             V( pMat->m_pEffect->Begin( &cPasses, 0 ) );
  150.             for( UINT p = 0; p < cPasses; ++p )
  151.             {
  152.                 V( pMat->m_pEffect->BeginPass( p ) );
  153.                 V( m_pMesh->DrawSubset( i ) );
  154.                 V( pMat->m_pEffect->EndPass() );
  155.             }
  156.             V( pMat->m_pEffect->End() );
  157.         }
  158.     }
  159. };
  160.  
  161.  
  162. class CMeshArcBall : public CD3DArcBall
  163. {
  164. public:
  165.     void OnBegin( int nX, int nY, D3DXMATRIXA16 *pmInvViewRotate )
  166.     {
  167.         m_bDrag = true;
  168.         m_qDown = m_qNow;
  169.         m_vDownPt = ScreenToVector( (float)nX, (float)nY );
  170.         D3DXVECTOR4 v;
  171.         D3DXVec3Transform( &v, &m_vDownPt, pmInvViewRotate );
  172.         m_vDownPt = (D3DXVECTOR3)v;
  173.     }
  174.     void OnMove( int nX, int nY, D3DXMATRIXA16 *pmInvViewRotate )
  175.     {
  176.         if (m_bDrag) 
  177.         { 
  178.             m_vCurrentPt = ScreenToVector( (float)nX, (float)nY );
  179.             D3DXVECTOR4 v;
  180.             D3DXVec3Transform( &v, &m_vCurrentPt, pmInvViewRotate );
  181.             m_vCurrentPt = (D3DXVECTOR3)v;
  182.             m_qNow = m_qDown * QuatFromBallPoints( m_vDownPt, m_vCurrentPt );
  183.         }
  184.     }
  185.     LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, D3DXMATRIXA16 *pmInvViewRotate )
  186.     {
  187.         // Current mouse position
  188.         int iMouseX = (short)LOWORD(lParam);
  189.         int iMouseY = (short)HIWORD(lParam);
  190.  
  191.         switch( uMsg )
  192.         {
  193.             case WM_LBUTTONDOWN:
  194.             case WM_LBUTTONDBLCLK:
  195.                 SetCapture( hWnd );
  196.                 OnBegin( iMouseX, iMouseY, pmInvViewRotate );
  197.                 return TRUE;
  198.  
  199.             case WM_LBUTTONUP:
  200.                 ReleaseCapture();
  201.                 OnEnd();
  202.                 return TRUE;
  203.  
  204.             case WM_MOUSEMOVE:
  205.                 if( MK_LBUTTON&wParam )
  206.                 {
  207.                     OnMove( iMouseX, iMouseY, pmInvViewRotate );
  208.                 }
  209.                 return TRUE;
  210.         }
  211.  
  212.         return FALSE;
  213.     }
  214. };
  215.  
  216.  
  217. //--------------------------------------------------------------------------------------
  218. // Global variables
  219. //--------------------------------------------------------------------------------------
  220. ID3DXFont*              g_pFont = NULL;         // Font for drawing text
  221. ID3DXSprite*            g_pTextSprite = NULL;   // Sprite for batching draw text calls
  222. ID3DXEffect*            g_pEffect = NULL;       // D3DX effect interface
  223. IDirect3DVertexDeclaration9 *g_pDecl = NULL;    // Vertex decl for meshes
  224. IDirect3DTexture9*      g_pDefaultTex = NULL;   // Default texture
  225. IDirect3DCubeTexture9*  g_pEnvMapTex = NULL;    // Environment map texture
  226. DWORD                   g_dwShaderFlags = 0;    // Shader creation flag for all effects
  227. CModelViewerCamera      g_Camera;               // Camera for navigation
  228. CGrowableArray<CMeshArcBall> g_ArcBall;
  229. bool                    g_bShowHelp = true;     // If true, it renders the UI control text
  230. CDXUTDialog             g_HUD;                  // dialog for standard controls
  231. CDXUTDialog             g_SampleUI;             // dialog for sample specific controls
  232. ID3DXEffectPool*        g_pEffectPool = NULL;   // Effect pool for sharing parameters
  233. CGrowableArray<CEffectMesh> g_Meshes;           // List of meshes being rendered
  234. CGrowableArray<D3DXMATRIXA16> g_amWorld;        // World transform for the meshes
  235. int                     g_nActiveMesh = 0;
  236. D3DXMATRIXA16           g_mScroll;              // Scroll matrix
  237. float                   g_fAngleToScroll = 0.0f;// Total angle to scroll the meshes in radian, in current scroll op
  238. float                   g_fAngleLeftToScroll = 0.0f;// Angle left to scroll the meshes in radian
  239.  
  240.  
  241. //--------------------------------------------------------------------------------------
  242. // UI control IDs
  243. //--------------------------------------------------------------------------------------
  244. #define IDC_TOGGLEFULLSCREEN    1
  245. #define IDC_TOGGLEREF           3
  246. #define IDC_CHANGEDEVICE        4
  247. #define IDC_SHARE               5
  248. #define IDC_SCROLLLEFT          6
  249. #define IDC_SCROLLRIGHT         7
  250. #define IDC_MESHNAME            8
  251. #define IDC_MATCOUNT            9
  252.  
  253.  
  254. //--------------------------------------------------------------------------------------
  255. // Forward declarations 
  256. //--------------------------------------------------------------------------------------
  257. bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed );
  258. void    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps );
  259. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  260. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  261. void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  262. void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  263. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing );
  264. void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown  );
  265. void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );
  266. void    CALLBACK OnLostDevice();
  267. void    CALLBACK OnDestroyDevice();
  268.  
  269. void    InitApp();
  270. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh );
  271. void    RenderText();
  272.  
  273.  
  274. HRESULT CEffectMesh::Create( LPCWSTR wszFileName, IDirect3DDevice9 *pd3dDevice )
  275. {
  276.     HRESULT hr;
  277.  
  278.     WCHAR str[MAX_PATH];
  279.     WCHAR wszMeshPath[MAX_PATH];
  280.     ID3DXBuffer *pAdjacency;
  281.     ID3DXBuffer *pMaterials;
  282.     ID3DXBuffer *pEffectInstance;
  283.     DWORD dwNumMaterials;
  284.  
  285.     // Save the mesh filename
  286.     wcsncpy( m_wszMeshFile, wszFileName, MAX_PATH );
  287.     m_wszMeshFile[ MAX_PATH - 1 ] = 0;
  288.  
  289.     V_RETURN( DXUTFindDXSDKMediaFileCch( wszMeshPath, MAX_PATH, m_wszMeshFile ) );
  290.     V_RETURN( D3DXLoadMeshFromX( wszMeshPath, D3DXMESH_MANAGED, pd3dDevice,
  291.                                     &pAdjacency, &pMaterials, &pEffectInstance,
  292.                                     &dwNumMaterials, &m_pMesh ) );
  293.     bool bHasNormals = ( m_pMesh->GetFVF() & D3DFVF_NORMAL ) != 0;
  294.     ID3DXMesh *pCloneMesh;
  295.     V_RETURN( m_pMesh->CloneMesh( m_pMesh->GetOptions(), MESHVERTEX::Decl, pd3dDevice, &pCloneMesh ) );
  296.     m_pMesh->Release();
  297.     m_pMesh = pCloneMesh;
  298.  
  299.     // Extract the path of the mesh file
  300.     WCHAR *pLastBSlash = wcsrchr( wszMeshPath, L'\\' );
  301.     if( pLastBSlash )
  302.     {
  303.         *( pLastBSlash + 1 ) = L'\0';
  304.     } else
  305.         lstrcpyW( wszMeshPath, L".\\" );
  306.  
  307.     // Ensure the mesh has correct normals.
  308.     if( !bHasNormals )
  309.         D3DXComputeNormals( m_pMesh, (DWORD*)pAdjacency->GetBufferPointer() );
  310.  
  311.     // Allocate material array
  312.     m_pMaterials = new CMeshMaterial[dwNumMaterials];
  313.     if( !m_pMaterials )
  314.         return E_OUTOFMEMORY;
  315.  
  316.     D3DXMATERIAL *pXMats = (D3DXMATERIAL *)pMaterials->GetBufferPointer();
  317.     D3DXEFFECTINSTANCE *pEI = (D3DXEFFECTINSTANCE *)pEffectInstance->GetBufferPointer();
  318.     for( UINT i = 0; i < dwNumMaterials; ++i )
  319.     {
  320.         // Obtain the effect
  321.  
  322.         hr = S_OK;
  323.         // Try the mesh's directory
  324.         lstrcpyW( str, wszMeshPath );
  325.         MultiByteToWideChar( CP_ACP, 0, pEI[i].pEffectFilename, -1, str + lstrlenW( str ), MAX_PATH );
  326.         // If the fx file is not in the same directory as the mesh, search the SDK paths.
  327.         if( INVALID_FILE_ATTRIBUTES == ::GetFileAttributesW( str ) )
  328.         {
  329.             WCHAR wszFxName[MAX_PATH];
  330.             // Search the SDK paths
  331.             MultiByteToWideChar( CP_ACP, 0, pEI[i].pEffectFilename, -1, wszFxName, MAX_PATH );
  332.             hr = DXUTFindDXSDKMediaFileCch( str, MAX_PATH, wszFxName );
  333.             if( FAILED( hr ) )
  334.             {
  335.                 // If this fx file can't be found, try searching SharedFx\FileName.
  336.                 MoveMemory( wszFxName + 9, wszFxName, ( lstrlenW( wszFxName ) + 1 ) * sizeof(WCHAR) );  // Make space for "SharedFx\"
  337.                 wcsncpy( wszFxName, L"SharedFx\\", 9 );
  338.                 hr = DXUTFindDXSDKMediaFileCch( str, MAX_PATH, wszFxName );
  339.             }
  340.         }
  341.  
  342.         if( SUCCEEDED( hr ) )
  343.             DXUTGetGlobalResourceCache().CreateEffectFromFile( pd3dDevice, str, NULL, NULL, g_dwShaderFlags, g_pEffectPool,
  344.                                                                &m_pMaterials[i].m_pEffect, NULL );
  345.         if( !m_pMaterials[i].m_pEffect )
  346.         {
  347.             // No valid effect for this material.  Use the default.
  348.             m_pMaterials[i].m_pEffect = g_pEffect;
  349.             m_pMaterials[i].m_pEffect->AddRef();
  350.         }
  351.  
  352.         // Set the technique this material should use
  353.         D3DXHANDLE hTech;
  354.         m_pMaterials[i].m_pEffect->FindNextValidTechnique( NULL, &hTech );
  355.         m_pMaterials[i].m_pEffect->SetTechnique( hTech );
  356.  
  357.         // Create a parameter block to include all parameters for the effect.
  358.         m_pMaterials[i].m_pEffect->BeginParameterBlock();
  359.         for( UINT param = 0; param < pEI[i].NumDefaults; ++param )
  360.         {
  361.             m_pMaterials[i].m_pEffect->SetValue( pEI[i].pDefaults[param].pParamName,
  362.                                                  pEI[i].pDefaults[param].pValue,
  363.                                                  pEI[i].pDefaults[param].NumBytes );
  364.         }
  365.  
  366.         // Obtain the texture
  367.         hr = S_OK;
  368.         // Try the mesh's directory first.
  369.         lstrcpyW( str, wszMeshPath );
  370.         MultiByteToWideChar( CP_ACP, 0, pXMats[i].pTextureFilename, -1, str + lstrlenW( str ), MAX_PATH );
  371.         // If the texture file is not in the same directory as the mesh, search the SDK paths.
  372.         if( INVALID_FILE_ATTRIBUTES == ::GetFileAttributesW( str ) )
  373.         {
  374.             WCHAR wszTexName[MAX_PATH];
  375.             // Search the SDK paths
  376.             MultiByteToWideChar( CP_ACP, 0, pXMats[i].pTextureFilename, -1, wszTexName, MAX_PATH );
  377.             hr = DXUTFindDXSDKMediaFileCch( str, MAX_PATH, wszTexName );
  378.         }
  379.  
  380.         if( SUCCEEDED( hr ) )
  381.             DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice, str, &m_pMaterials[i].m_pTexture );
  382.         if( !m_pMaterials[i].m_pTexture )
  383.         {
  384.             // No texture or texture fails to load. Use the default texture.
  385.             m_pMaterials[i].m_pTexture = g_pDefaultTex;
  386.             m_pMaterials[i].m_pTexture->AddRef();
  387.         }
  388.  
  389.         // Include the texture in the parameter block if the effect requires one.
  390.         D3DXHANDLE hTexture = m_pMaterials[i].m_pEffect->GetParameterByName( NULL, "g_txScene" );
  391.         if( hTexture )
  392.             m_pMaterials[i].m_pEffect->SetTexture( hTexture, m_pMaterials[i].m_pTexture );
  393.  
  394.         // Include the environment map texture in the parameter block if the effect requires one.
  395.         hTexture = m_pMaterials[i].m_pEffect->GetParameterByName( NULL, "g_txEnvMap" );
  396.         if( hTexture )
  397.             m_pMaterials[i].m_pEffect->SetTexture( hTexture, g_pEnvMapTex );
  398.  
  399.         // Save the parameter block
  400.         m_pMaterials[i].m_hParam = m_pMaterials[i].m_pEffect->EndParameterBlock();
  401.     }
  402.  
  403.     SAFE_RELEASE( pAdjacency );
  404.     SAFE_RELEASE( pMaterials );
  405.     SAFE_RELEASE( pEffectInstance );
  406.     m_dwNumMaterials = dwNumMaterials;
  407.     return S_OK;
  408. }
  409.  
  410.  
  411. //--------------------------------------------------------------------------------------
  412. // Entry point to the program. Initializes everything and goes into a message processing 
  413. // loop. Idle time is used to render the scene.
  414. //--------------------------------------------------------------------------------------
  415. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  416. {
  417.     _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
  418.  
  419.     // Set the callback functions. These functions allow the sample framework to notify
  420.     // the application about device changes, user input, and windows messages.  The 
  421.     // callbacks are optional so you need only set callbacks for events you're interested 
  422.     // in. However, if you don't handle the device reset/lost callbacks then the sample 
  423.     // framework won't be able to reset your device since the application must first 
  424.     // release all device resources before resetting.  Likewise, if you don't handle the 
  425.     // device created/destroyed callbacks then the sample framework won't be able to 
  426.     // recreate your device resources.
  427.     DXUTSetCallbackDeviceCreated( OnCreateDevice );
  428.     DXUTSetCallbackDeviceReset( OnResetDevice );
  429.     DXUTSetCallbackDeviceLost( OnLostDevice );
  430.     DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
  431.     DXUTSetCallbackMsgProc( MsgProc );
  432.     DXUTSetCallbackKeyboard( KeyboardProc );
  433.     DXUTSetCallbackFrameRender( OnFrameRender );
  434.     DXUTSetCallbackFrameMove( OnFrameMove );
  435.  
  436.     // Show the cursor and clip it when in full screen
  437.     DXUTSetCursorSettings( true, true );
  438.  
  439.     InitApp();
  440.  
  441.     // Initialize the sample framework and create the desired Win32 window and Direct3D 
  442.     // device for the application. Calling each of these functions is optional, but they
  443.     // allow you to set several options which control the behavior of the framework.
  444.     DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  445.     DXUTCreateWindow( L"EffectParam" );
  446.     DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );
  447.  
  448.     // Pass control to the sample framework for handling the message pump and 
  449.     // dispatching render calls. The sample framework will call your FrameMove 
  450.     // and FrameRender callback when there is idle time between handling window messages.
  451.     DXUTMainLoop();
  452.  
  453.     // Perform any application-level cleanup here. Direct3D device resources are released within the
  454.     // appropriate callback functions and therefore don't require any cleanup code here.
  455.  
  456.     return DXUTGetExitCode();
  457. }
  458.  
  459.  
  460. //--------------------------------------------------------------------------------------
  461. // Initialize the app 
  462. //--------------------------------------------------------------------------------------
  463. void InitApp()
  464. {
  465.     // Initialize dialogs
  466.     g_HUD.SetCallback( OnGUIEvent ); int iY = 10; 
  467.     g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 );
  468.     g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22 );
  469.     g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22 );
  470.  
  471.     g_SampleUI.SetCallback( OnGUIEvent ); iY = 10;
  472.     g_SampleUI.AddStatic( IDC_MESHNAME, L"Mesh Name", 0, iY, 160, 20 );
  473.     g_SampleUI.AddStatic( IDC_MATCOUNT, L"Number of materials: 0", 0, iY += 20, 160, 20 );
  474.     g_SampleUI.AddButton( IDC_SCROLLLEFT, L"<<", 5, iY += 24, 70, 24 );
  475.     g_SampleUI.AddButton( IDC_SCROLLRIGHT, L">>", 85, iY, 70, 24 );
  476.     g_SampleUI.AddCheckBox( IDC_SHARE, L"Enable shared parameters", 0, iY += 32, 160, 24, true );
  477.  
  478.     // Initialize the arcball
  479.     for( int i = 0; i < sizeof(g_MeshListData)/sizeof(g_MeshListData[0]); ++i )
  480.     {
  481.         g_ArcBall.Add( CMeshArcBall() );
  482.         g_ArcBall[g_ArcBall.GetSize()-1].SetTranslationRadius( 2.0f );
  483.     }
  484.  
  485.     // Setup the cameras
  486.     D3DXVECTOR3 vecEye(0.0f, 0.0f, -5.0f);
  487.     D3DXVECTOR3 vecAt (0.0f, 0.0f, -3.0f);
  488.     g_Camera.SetViewParams( &vecEye, &vecAt );
  489.     g_Camera.SetButtonMasks( 0, MOUSE_WHEEL, 0 );
  490.     g_Camera.SetRadius( 5.0f, 1.0f );
  491. }
  492.  
  493.  
  494. //--------------------------------------------------------------------------------------
  495. // Called during device initialization, this code checks the device for some 
  496. // minimum set of capabilities, and rejects those that don't pass by returning false.
  497. //--------------------------------------------------------------------------------------
  498. bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
  499.                                   D3DFORMAT BackBufferFormat, bool bWindowed )
  500. {
  501.     // Skip backbuffer formats that don't support alpha blending
  502.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  503.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  504.                     AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  505.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  506.         return false;
  507.  
  508.     // Must support pixel shader 1.1
  509.     if( pCaps->PixelShaderVersion < D3DPS_VERSION( 1, 1 ) )
  510.         return false;
  511.  
  512.     return true;
  513. }
  514.  
  515.  
  516. //--------------------------------------------------------------------------------------
  517. // This callback function is called immediately before a device is created to allow the 
  518. // application to modify the device settings. The supplied pDeviceSettings parameter 
  519. // contains the settings that the framework has selected for the new device, and the 
  520. // application can make any desired changes directly to this structure.  Note however that 
  521. // the sample framework will not correct invalid device settings so care must be taken 
  522. // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.  
  523. //--------------------------------------------------------------------------------------
  524. void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps )
  525. {
  526.     // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  527.     // then switch to SWVP.
  528.     if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  529.          pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
  530.     {
  531.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  532.     }
  533.     else
  534.     {
  535.         pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  536.     }
  537.  
  538.     // This application is designed to work on a pure device by not using 
  539.     // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP.
  540.     if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && 
  541.         (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 )
  542.         pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE;
  543.  
  544.     // If the hardware cannot do vertex blending, use software vertex processing.
  545.     if( pCaps->MaxVertexBlendMatrices < 2 )
  546.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  547.  
  548.     // If using hardware vertex processing, change to mixed vertex processing
  549.     // so there is a fallback.
  550.     if( pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING )
  551.         pDeviceSettings->BehaviorFlags = D3DCREATE_MIXED_VERTEXPROCESSING;    
  552.  
  553.  
  554.     // Debugging vertex shaders requires either REF or software vertex processing 
  555.     // and debugging pixel shaders requires REF.  
  556. #ifdef DEBUG_VS
  557.     if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF )
  558.     {
  559.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  560.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE;
  561.         pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  562.     }
  563. #endif
  564. #ifdef DEBUG_PS
  565.     pDeviceSettings->DeviceType = D3DDEVTYPE_REF;
  566. #endif
  567. }
  568.  
  569.  
  570. //--------------------------------------------------------------------------------------
  571. // This callback function will be called immediately after the Direct3D device has been 
  572. // created, which will happen during application initialization and windowed/full screen 
  573. // toggles. This is the best location to create D3DPOOL_MANAGED resources since these 
  574. // resources need to be reloaded whenever the device is destroyed. Resources created  
  575. // here should be released in the OnDestroyDevice callback. 
  576. //--------------------------------------------------------------------------------------
  577. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  578. {
  579.     HRESULT hr;
  580.     WCHAR str[MAX_PATH];
  581.  
  582.     // Create the effect pool object if shared param is enabled
  583.     if( g_SampleUI.GetCheckBox( IDC_SHARE )->GetChecked() )
  584.         V_RETURN( D3DXCreateEffectPool( &g_pEffectPool ) );
  585.  
  586.     // Create the vertex decl
  587.     V_RETURN( pd3dDevice->CreateVertexDeclaration( MESHVERTEX::Decl, &g_pDecl ) );
  588.     pd3dDevice->SetVertexDeclaration( g_pDecl );
  589.  
  590.     // Create the 1x1 white default texture
  591.     V_RETURN( pd3dDevice->CreateTexture( 1, 1, 1, 0, D3DFMT_A8R8G8B8,
  592.                                          D3DPOOL_MANAGED, &g_pDefaultTex, NULL ) );
  593.     D3DLOCKED_RECT lr;
  594.     V_RETURN( g_pDefaultTex->LockRect( 0, &lr, NULL, 0 ) );
  595.     *(LPDWORD)lr.pBits = D3DCOLOR_RGBA( 255, 255, 255, 255 );
  596.     V_RETURN( g_pDefaultTex->UnlockRect( 0 ) );
  597.  
  598.     // Create the environment map texture
  599.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"lobby\\lobbycube.dds" ) );
  600.     V_RETURN( D3DXCreateCubeTextureFromFile( pd3dDevice, str, &g_pEnvMapTex ) );
  601.  
  602.     // Initialize the font
  603.     V_RETURN( DXUTGetGlobalResourceCache().CreateFont( pd3dDevice, 15, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, 
  604.                                                        OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  605.                                                        L"Arial", &g_pFont ) );
  606.  
  607.     // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
  608.     // shader debugger. Debugging vertex shaders requires either REF or software vertex 
  609.     // processing, and debugging pixel shaders requires REF.  The 
  610.     // D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
  611.     // shader debugger.  It enables source level debugging, prevents instruction 
  612.     // reordering, prevents dead code elimination, and forces the compiler to compile 
  613.     // against the next higher available software target, which ensures that the 
  614.     // unoptimized shaders do not exceed the shader model limitations.  Setting these 
  615.     // flags will cause slower rendering since the shaders will be unoptimized and 
  616.     // forced into software.  See the DirectX documentation for more information about 
  617.     // using the shader debugger.
  618.     #ifdef DEBUG_VS
  619.         g_dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
  620.     #endif
  621.     #ifdef DEBUG_PS
  622.         g_dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
  623.     #endif
  624.  
  625.     // Read the D3DX effect file
  626.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"EffectParam.fx" ) );
  627.  
  628.     // If this fails, there should be debug output as to 
  629.     // they the .fx file failed to compile
  630.     V_RETURN( DXUTGetGlobalResourceCache().CreateEffectFromFile( pd3dDevice, str, NULL, NULL, g_dwShaderFlags, 
  631.                                                                  g_pEffectPool, &g_pEffect, NULL ) );
  632.  
  633.     // Create the meshes
  634.     for( int i = 0; i < sizeof(g_MeshListData)/sizeof(g_MeshListData[0]); ++i )
  635.     {
  636.         CEffectMesh NewMesh;
  637.         if( SUCCEEDED( NewMesh.Create( g_MeshListData[i].wszFile, DXUTGetD3DDevice() ) ) )
  638.         {
  639.             g_Meshes.Add( NewMesh );
  640.             D3DXMATRIXA16 mW;
  641.             LPVOID pVerts = NULL;
  642.             D3DXMatrixIdentity( &mW );
  643.             if( SUCCEEDED( NewMesh.GetMesh()->LockVertexBuffer( 0, &pVerts ) ) )
  644.             {
  645.                 D3DXVECTOR3 vCtr;
  646.                 float fRadius;
  647.                 if( SUCCEEDED( D3DXComputeBoundingSphere( (const D3DXVECTOR3*)pVerts,
  648.                                                         NewMesh.GetMesh()->GetNumVertices(),
  649.                                                         NewMesh.GetMesh()->GetNumBytesPerVertex(),
  650.                                                         &vCtr, &fRadius ) ) )
  651.                 {
  652.                     D3DXMatrixTranslation( &mW, -vCtr.x, -vCtr.y, -vCtr.z );
  653.                     D3DXMATRIXA16 m;
  654.                     D3DXMatrixScaling( &m, 1.0f / fRadius,
  655.                                             1.0f / fRadius,
  656.                                             1.0f / fRadius );
  657.                     D3DXMatrixMultiply( &mW, &mW, &m );
  658.                 }
  659.                 NewMesh.GetMesh()->UnlockVertexBuffer();
  660.             }
  661.  
  662.             g_MeshListData[i].dwNumMat = NewMesh.GetNumMaterials();
  663.             g_amWorld.Add( mW );
  664.  
  665.             // Set the arcball window size
  666.             const D3DSURFACE_DESC* pD3DSD = DXUTGetBackBufferSurfaceDesc();
  667.             g_ArcBall[g_ArcBall.GetSize()-1].SetWindow( pD3DSD->Width, pD3DSD->Height );
  668.         }
  669.     }
  670.  
  671.     g_SampleUI.GetStatic( IDC_MESHNAME )->SetText( g_MeshListData[g_nActiveMesh].wszName );
  672.     WCHAR wsz[256];
  673.     _snwprintf( wsz, 256, L"Number of materials: %u", g_MeshListData[g_nActiveMesh].dwNumMat );
  674.     wsz[255] = L'\0';
  675.     g_SampleUI.GetStatic( IDC_MATCOUNT )->SetText( wsz );
  676.  
  677.     D3DXMatrixIdentity( &g_mScroll );
  678.  
  679.     return S_OK;
  680. }
  681.  
  682.  
  683. //--------------------------------------------------------------------------------------
  684. // This callback function will be called immediately after the Direct3D device has been 
  685. // reset, which will happen after a lost device scenario. This is the best location to 
  686. // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
  687. // the device is lost. Resources created here should be released in the OnLostDevice 
  688. // callback. 
  689. //--------------------------------------------------------------------------------------
  690. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
  691.                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  692. {
  693.     HRESULT hr;
  694.  
  695.     if( g_pFont )
  696.         V_RETURN( g_pFont->OnResetDevice() );
  697.     if( g_pEffect )
  698.         V_RETURN( g_pEffect->OnResetDevice() );
  699.  
  700.     // Create a sprite to help batch calls when drawing many lines of text
  701.     V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) );
  702.  
  703.     // Setup the camera's projection parameters
  704.     float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  705.     g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f );
  706.     for( int i = 0; i < g_ArcBall.GetSize(); ++i )
  707.         g_ArcBall[i].SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
  708.  
  709.     g_HUD.SetLocation( pBackBufferSurfaceDesc->Width-170, 0 );
  710.     g_HUD.SetSize( 170, 170 );
  711.     g_SampleUI.SetLocation( ( pBackBufferSurfaceDesc->Width-170 ) / 2, pBackBufferSurfaceDesc->Height-120 );
  712.     g_SampleUI.SetSize( 170, 120 );
  713.  
  714.     return S_OK;
  715. }
  716.  
  717.  
  718. //--------------------------------------------------------------------------------------
  719. // This callback function will be called once at the beginning of every frame. This is the
  720. // best location for your application to handle updates to the scene, but is not 
  721. // intended to contain actual rendering calls, which should instead be placed in the 
  722. // OnFrameRender callback.  
  723. //--------------------------------------------------------------------------------------
  724. void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  725. {
  726.     // Update the scroll matrix
  727.     float fFrameAngleToScroll = g_fAngleToScroll * fElapsedTime / SCROLL_TIME;
  728.     if( fabs( fFrameAngleToScroll ) > fabs( g_fAngleLeftToScroll ) )
  729.         fFrameAngleToScroll = g_fAngleLeftToScroll;
  730.     g_fAngleLeftToScroll -= fFrameAngleToScroll;
  731.     D3DXMATRIXA16 m;
  732.     D3DXMatrixRotationY( &m, fFrameAngleToScroll );
  733.     g_mScroll *= m;
  734.     // Update the camera's position based on user input 
  735.     g_Camera.FrameMove( fElapsedTime );
  736. }
  737.  
  738.  
  739. //--------------------------------------------------------------------------------------
  740. // This callback function will be called at the end of every frame to perform all the 
  741. // rendering calls for the scene, and it will also be called if the window needs to be 
  742. // repainted. After this function has returned, the sample framework will call 
  743. // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
  744. //--------------------------------------------------------------------------------------
  745. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  746. {
  747.     HRESULT hr;
  748.     D3DXMATRIXA16 mWorld;
  749.     D3DXMATRIXA16 mWorldView;
  750.     D3DXMATRIXA16 mViewProj;
  751.     D3DXMATRIXA16 mWorldViewProjection;
  752.  
  753.     // Clear the render target and the zbuffer 
  754.     V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 66, 75, 121), 1.0f, 0) );
  755.  
  756.     // Render the scene
  757.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  758.     {
  759.         // Get the projection & view matrix from the camera class
  760.         mViewProj = *g_Camera.GetViewMatrix() * *g_Camera.GetProjMatrix();
  761.  
  762.         // Update the effect's variables.  Instead of using strings, it would 
  763.         // be more efficient to cache a handle to the parameter by calling 
  764.         // ID3DXEffect::GetParameterByName
  765.         D3DXMATRIXA16 mViewInv;
  766.         D3DXMatrixInverse( &mViewInv, NULL, g_Camera.GetViewMatrix() );
  767.         V( g_pEffect->SetMatrix( "g_mViewInv", &mViewInv ) );
  768.         D3DXVECTOR4 vLightView( 0.0f, 0.0f, -10.0f, 1.0f );
  769.         V( g_pEffect->SetVector( "g_vLight", &vLightView ) );
  770.  
  771.         float fAngleDelta = D3DX_PI * 2.0f / g_Meshes.GetSize();
  772.         for( int i = 0; i < g_Meshes.GetSize(); ++i )
  773.         {
  774.             D3DXMATRIXA16 mWorld = *g_ArcBall[i].GetRotationMatrix() * *g_ArcBall[i].GetTranslationMatrix();
  775.             mWorld = g_amWorld[i] * mWorld;
  776.             D3DXMATRIXA16 mRot;
  777.             D3DXMATRIXA16 mTrans;
  778.             D3DXMatrixTranslation( &mTrans, 0.0f, 0.0f, -3.0f );
  779.             D3DXMatrixRotationY( &mRot, fAngleDelta * ( i - g_nActiveMesh ) );
  780.             mWorld *= mTrans * mRot * g_mScroll;
  781.             mWorldView = mWorld * *g_Camera.GetViewMatrix();
  782.             mWorldViewProjection = mWorld * mViewProj;
  783.             V( g_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProjection ) );
  784.             V( g_pEffect->SetMatrix( "g_mWorldView", &mWorldView ) );
  785.             g_Meshes[i].Render( pd3dDevice );
  786.         }
  787.  
  788.         RenderText();
  789.         V( g_HUD.OnRender( fElapsedTime ) );
  790.         V( g_SampleUI.OnRender( fElapsedTime ) );
  791.  
  792.         V( pd3dDevice->EndScene() );
  793.     }
  794.  
  795.     if( g_fAngleLeftToScroll == 0.0f )
  796.     {
  797.         D3DXMatrixIdentity( &g_mScroll );
  798.     }
  799. }
  800.  
  801.  
  802. //--------------------------------------------------------------------------------------
  803. // Render the help and statistics text. This function uses the ID3DXFont interface for 
  804. // efficient text rendering.
  805. //--------------------------------------------------------------------------------------
  806. void RenderText()
  807. {
  808.     // The helper object simply helps keep track of text position, and color
  809.     // and then it calls pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr );
  810.     // If NULL is passed in as the sprite object, then it will work however the 
  811.     // pFont->DrawText() will not be batched together.  Batching calls will improves performance.
  812.     CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
  813.  
  814.     // Output statistics
  815.     txtHelper.Begin();
  816.     txtHelper.SetInsertionPos( 5, 5 );
  817.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  818.     txtHelper.DrawTextLine( DXUTGetFrameStats() );
  819.     txtHelper.DrawTextLine( DXUTGetDeviceStats() );
  820.  
  821.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  822.     txtHelper.DrawFormattedTextLine( L"Number of meshes: %d\n", g_Meshes.GetSize() );
  823.  
  824.     // Draw help
  825.     if( g_bShowHelp )
  826.     {
  827.         const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc();
  828.         txtHelper.SetInsertionPos( 10, pd3dsdBackBuffer->Height-15*6 );
  829.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) );
  830.         txtHelper.DrawTextLine( L"Controls (F1 to hide):" );
  831.  
  832.         txtHelper.SetInsertionPos( 40, pd3dsdBackBuffer->Height-15*5 );
  833.         txtHelper.DrawTextLine( L"Rotate Mesh: Left mouse drag\n"
  834.                                 L"Zoom: Mouse wheel\n"
  835.                                 L"Quit: ESC" );
  836.     }
  837.     else
  838.     {
  839.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  840.         txtHelper.DrawTextLine( L"Press F1 for help" );
  841.     }
  842.  
  843.     // Draw shared param description
  844.     txtHelper.SetInsertionPos( 5, 50 );
  845.     if( g_pEffectPool )
  846.     {
  847.         txtHelper.SetForegroundColor( D3DXCOLOR( 0.0f, 1.0f, 0.0f, 1.0f ) );
  848.         txtHelper.DrawTextLine( L"Shared parameters are enabled.  When updating transformation\n"
  849.                                 L"matrices on one effect object, all effect objects automatically\n"
  850.                                 L"see the updated values." );
  851.     }
  852.     else
  853.     {
  854.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ) );
  855.         txtHelper.DrawTextLine( L"Shared parameters are disabled.  When transformation matrices\n"
  856.                                 L"are updated on the default effect object (diffuse only), only that\n"
  857.                                 L"effect object has the up-to-date values.  All other effect objects\n"
  858.                                 L"do not have valid matrices for rendering." );
  859.     }
  860.  
  861.     txtHelper.End();
  862. }
  863.  
  864.  
  865. //--------------------------------------------------------------------------------------
  866. // Before handling window messages, the sample framework passes incoming windows 
  867. // messages to the application through this callback function. If the application sets 
  868. // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message.
  869. //--------------------------------------------------------------------------------------
  870. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
  871. {
  872.     // Give the dialogs a chance to handle the message first
  873.     *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  874.     if( *pbNoFurtherProcessing )
  875.         return 0;
  876.     *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
  877.     if( *pbNoFurtherProcessing )
  878.         return 0;
  879.  
  880.     // Pass all remaining windows messages to camera so it can respond to user input
  881.     g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  882.     D3DXMATRIXA16 mViewRotate = *g_Camera.GetViewMatrix();
  883.     mViewRotate._41 = mViewRotate._42 = mViewRotate._43 = 0.0f;
  884.     D3DXMatrixInverse( &mViewRotate, NULL, &mViewRotate );
  885.     if( g_ArcBall.GetSize() > 0 )
  886.         g_ArcBall[g_nActiveMesh].HandleMessages( hWnd, uMsg, wParam, lParam, &mViewRotate );
  887.  
  888.     return 0;
  889. }
  890.  
  891.  
  892. //--------------------------------------------------------------------------------------
  893. // As a convenience, the sample framework inspects the incoming windows messages for
  894. // keystroke messages and decodes the message parameters to pass relevant keyboard
  895. // messages to the application.  The framework does not remove the underlying keystroke 
  896. // messages, which are still passed to the application's MsgProc callback.
  897. //--------------------------------------------------------------------------------------
  898. void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
  899. {
  900.     if( bKeyDown )
  901.     {
  902.         switch( nChar )
  903.         {
  904.             case VK_F1: g_bShowHelp = !g_bShowHelp; break;
  905.         }
  906.     }
  907. }
  908.  
  909.  
  910. //--------------------------------------------------------------------------------------
  911. // Handles the GUI events
  912. //--------------------------------------------------------------------------------------
  913. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl )
  914. {
  915.     switch( nControlID )
  916.     {
  917.         case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;
  918.         case IDC_TOGGLEREF:        DXUTToggleREF(); break;
  919.         case IDC_CHANGEDEVICE:     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break;
  920.  
  921.         case IDC_SHARE:
  922.         {
  923.             // Shared param status changed. Destroy and recreate everything
  924.             // with or without effect pool as appropriate.
  925.             if( DXUTGetD3DDevice() )
  926.             {
  927.                 // We need to call the callbacks of the resource manager or the ref
  928.                 // count will not reach 0.
  929.  
  930.                 OnLostDevice();
  931.                 DXUTGetGlobalResourceCache().OnLostDevice();
  932.                 OnDestroyDevice();
  933.                 DXUTGetGlobalResourceCache().OnDestroyDevice();
  934.                 OnCreateDevice( DXUTGetD3DDevice(), DXUTGetBackBufferSurfaceDesc() );
  935.                 DXUTGetGlobalResourceCache().OnCreateDevice( DXUTGetD3DDevice() );
  936.                 OnResetDevice( DXUTGetD3DDevice(), DXUTGetBackBufferSurfaceDesc() );
  937.                 DXUTGetGlobalResourceCache().OnResetDevice( DXUTGetD3DDevice() );
  938.             }
  939.             break;
  940.         }
  941.  
  942.         case IDC_SCROLLLEFT:
  943.         case IDC_SCROLLRIGHT:
  944.         {
  945.             // Only scroll if we have more than one mesh
  946.             if( g_Meshes.GetSize() <= 1 )
  947.                 break;
  948.  
  949.             // Only scroll if we are not already scrolling
  950.             if( g_fAngleLeftToScroll != 0.0f )
  951.                 break;
  952.  
  953.             // Compute the angle to scroll
  954.             g_fAngleToScroll = g_fAngleLeftToScroll = nControlID == IDC_SCROLLLEFT ? -D3DX_PI * 2.0f / g_Meshes.GetSize() :
  955.                                                                                      D3DX_PI * 2.0f / g_Meshes.GetSize();
  956.  
  957.             // Initialize the scroll matrix to be reverse full-angle rotation,
  958.             // then gradually decrease to zero (identity).
  959.             D3DXMatrixRotationY( &g_mScroll, -g_fAngleToScroll );
  960.             // Update front mesh index
  961.             if( nControlID == IDC_SCROLLLEFT )
  962.             {
  963.                 ++g_nActiveMesh;
  964.                 if( g_nActiveMesh == g_Meshes.GetSize() )
  965.                     g_nActiveMesh = 0;
  966.             }
  967.             else
  968.             {
  969.                 --g_nActiveMesh;
  970.                 if( g_nActiveMesh < 0 )
  971.                     g_nActiveMesh = g_Meshes.GetSize() - 1;
  972.             }
  973.  
  974.             // Update mesh name and material count
  975.             g_SampleUI.GetStatic( IDC_MESHNAME )->SetText( g_MeshListData[g_nActiveMesh].wszName );
  976.             WCHAR wsz[256];
  977.             _snwprintf( wsz, 256, L"Number of materials: %u", g_MeshListData[g_nActiveMesh].dwNumMat );
  978.             wsz[255] = L'\0';
  979.             g_SampleUI.GetStatic( IDC_MATCOUNT )->SetText( wsz );
  980.  
  981.             break;
  982.         }
  983.     }
  984. }
  985.  
  986.  
  987. //--------------------------------------------------------------------------------------
  988. // This callback function will be called immediately after the Direct3D device has 
  989. // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
  990. // in the OnResetDevice callback should be released here, which generally includes all 
  991. // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
  992. // information about lost devices.
  993. //--------------------------------------------------------------------------------------
  994. void CALLBACK OnLostDevice()
  995. {
  996.     if( g_pFont )
  997.         g_pFont->OnLostDevice();
  998.     if( g_pEffect )
  999.         g_pEffect->OnLostDevice();
  1000.     SAFE_RELEASE(g_pTextSprite);
  1001. }
  1002.  
  1003.  
  1004. //--------------------------------------------------------------------------------------
  1005. // This callback function will be called immediately after the Direct3D device has 
  1006. // been destroyed, which generally happens as a result of application termination or 
  1007. // windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  1008. // should be released here, which generally includes all D3DPOOL_MANAGED resources. 
  1009. //--------------------------------------------------------------------------------------
  1010. void CALLBACK OnDestroyDevice()
  1011. {
  1012.     SAFE_RELEASE( g_pEffect );
  1013.     SAFE_RELEASE( g_pFont );
  1014.     SAFE_RELEASE( g_pDefaultTex );
  1015.     SAFE_RELEASE( g_pEffectPool );
  1016.     SAFE_RELEASE( g_pDecl );
  1017.     SAFE_RELEASE( g_pEnvMapTex );
  1018.  
  1019.     for( int i = 0; i < g_Meshes.GetSize(); ++i )
  1020.         g_Meshes[i].Destroy();
  1021.  
  1022.     g_Meshes.RemoveAll();
  1023.     g_amWorld.RemoveAll();
  1024. }
  1025.